LOADING...

加载过慢请开启缓存(浏览器默认开启)

loading

BFC

2023/3/12 前端

什么是BFC

BFC(Block Formatting Context,块级格式化上下文),一个BFC区域包含创建该上下文元素的所有子元素,但是不包括创建了新的BFC的子元素的内部元素,BFC是是一块独立的渲染区域,可以将BFC看成是元素的一种属性,拥有了这种属性的元素就会使它的子元素与世隔绝,不会影响到外部其他元素。

例如:

<div class="box1">
    <div class="box2"></div>
    <div class="box3"></div>
    <div class="box4"></div>
    <div class="box5">
        <div class="box6"></div>
        <div class="box7"></div>
        <div class="box8"></div>
    </div>
</div>

假设box1和box5是两个BFC区域,box1这个BFC区域包含了子元素box2、3、4、5,但不包括box6、7、8;box5的区域包含box6、7、8这三个子元素。

总结:

  • 每个BFC区域只包括其子元素,不包括其子元素的子元素
  • 每一个BFC区域都是独立隔绝的,互不影响

BFC原理(渲染规则|布局规则)

  • 内部的Box会在垂直方向,从顶部开始一个接一个的放置
  • Box垂直方向的距离由margin决定,属于同一个BFC的两个相邻的Box的margin会发生重叠
  • 每个元素的margin box 的左边,与包含块border Box的左边相接触,即使存在浮动也是如此
  • BFC在页面上是一个隔离的独立容器,外面的元素不会影响里面的元素,反之亦然
  • BFC的区域不会与float Box重叠(可以用这个特性清除浮动)
  • 计算BFC的高度时,浮动元素也参与计算(解决父盒子塌陷)

如何使一个元素变为BFC区域

  • body根元素
  • 设置浮动(不包括none)
  • 设置绝对定位,absoulte或者fixed
  • 行内块显示模式:display为inline-block
  • 设置overflow,即hidden,auto,scroll
  • 表格单元,table-cell、table等属性
  • 弹性布局flex或inline-flex

BFC作用

  • 解决外边距的塌陷问题(垂直塌陷)
<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .div {
      width: 100px;
      height: 100px;
      background-color: red;
      margin: 100px;
    }
  </style>
</head>

<body>
  <div class="div"></div>
  <div class="div"></div>
</body>

</html>

但是这两个盒子之间的距离为100px,出现了垂直塌陷(同一个BFC区域的兄弟元素或父子元素会重叠margin),解决方案:给两个盒子都加一个父元素,并且将父元素设置为BFC区域,就可以解决margin塌陷问题。

解决方案:

<style>
    .div{
    width: 100px;
    height: 100px;
    background-color: red;
    margin: 100px;
    }
    .div_bfc{
        overflow:hidden;
    }
</style>

<div class="div_bfc">
    <div class="div"></div>
</div>
<div class="div_bfc">
    <div class="div"></div>
</div>
  • 利用BFC解决包含塌陷

有时候给子元素加margin会带着父元素一起跑

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .father {
      width: 100px;
      height: 100px;
      background-color: red;
    }

    .son {
      width: 20px;
      height: 20px;
      background-color: black;
      margin-top: 20px;
    }
  </style>
</head>

<body>
  <div class="father">
    <div class="son"></div>
  </div>
</body>

</html>

在这个例子中,只给son设置margin-top为20px,father会被带着一起走。解决方案:padding/BFC,后者将父盒子变为BFC区域,这样在BFC区域内部的操作不会影响到外部。(父元素的margin算是在父元素外部)

解决方案:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .father {
      width: 100px;
      height: 100px;
      background-color: red;
      overflow: hidden;
    }

    .son {
      width: 20px;
      height: 20px;
      background-color: black;
      margin-top: 20px;
    }
  </style>
</head>

<body>
  <div class="father">
    <div class="son"></div>
  </div>
</body>

</html>
  • 清除浮动

浮动会导致父元素高度塌陷,清除浮动的方式:overflow:hidden

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .father {
      width: 100px;
      background-color: red;
    }

    .son {
      width: 20px;
      height: 20px;
      background-color: black;
      /*
        float:right
        这句话设置之后父容器会塌陷
      */
    }
  </style>
</head>

<body>
  <div class="father">
    <div class="son"></div>
  </div>
</body>

</html>

在上例中,不设置父元素的高度,子元素会自动将父元素撑开,但是将子元素设置浮动之后,父元素的高度会塌陷;为了解决这个问题,将父元素设置为BFC区域:overflow:hidden;

原理:独立的块级上下文可以包裹浮动流,全部浮动子元素也不会引起容器高度塌陷,包含块会把浮动元素的高度也计算在内,所以就不用清除浮动来撑起包含块的高度。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .father {
      width: 100px;
      background-color: red;
      overflow: hidden;
    }

    .son {
      width: 20px;
      height: 20px;
      background-color: black;
      float: right;
    }
  </style>
</head>

<body>
  <div class="father">
    <div class="son"></div>
  </div>
</body>

</html>
  • BFC可以阻止标准流元素被浮动元素覆盖

因为浮动元素会脱离文档流,跑到上一个层面,所以可能会导致浮动元素覆盖基本元素的问题。

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .red {
      width: 200px;
      height: 200px;
      background-color: red;
      float: left;
    }

    .blue {
      height: 300px;
      background-color: blue;
    }
  </style>
</head>

<body>
  <div class="red"></div>
  <div class="blue"></div>
</body>

</html>

在上例中,红色块设置浮动,会覆盖蓝色块,为了让蓝色块不受红色块影响,让蓝色块触发BFC

解决方案:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8">
  <title>Title</title>
  <style>
    .red {
      width: 200px;
      height: 200px;
      background-color: red;
      float: left;
    }

    .blue {
      height: 300px;
      background-color: blue;
      overflow: hidden;
    }
  </style>
</head>

<body>
  <div class="red"></div>
  <div class="blue"></div>
</body>

</html>

让蓝色块触发BFC之后,他就会避开左边的宽度,自适应自己的宽度。